/*
 * Copyright 2010 Christoph Widulle (christoph.widulle@googlemail.com)
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the
 * License. You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS"
 * BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language
 * governing permissions and limitations under the License.
 */




package com.android1.amarena2d.engine.render;

import com.android1.amarena2d.commons.BlendFunction;
import com.android1.amarena2d.engine.GL;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.GL10;
import com.badlogic.gdx.graphics.SpriteBatch;
import com.badlogic.gdx.graphics.Texture;

/**
 * @author cwidulle
 */
public class AmarenaSpriteBatch extends SpriteBatch {

    BlendFunction blendFunction = BlendFunction.DEFAULT;

    public void begin() {
        idx = 0;
        lastTexture = null;
        drawing = true;
    }


    public void end() {
        if (!drawing)
            throw new IllegalStateException(
                    "you have to call SpriteBatch.begin() first");
        if (idx > 0)
            renderMesh();
        lastTexture = null;
        idx = 0;
        drawing = false;
    }

    public void draw(Texture texture, float x, float y, float width, float height, Color tint) {
        if (!drawing)
            throw new IllegalStateException(
                    "you have to call SpriteBatch.begin() first");

        if (texture != lastTexture) {
            renderMesh();
            lastTexture = texture;
            invTexWidth = 1.0f / texture.getWidth();
            invTexHeight = 1.0f / texture.getHeight();
        } else if (idx == vertices.length)
            renderMesh();

        final float u = 0;
        final float v = 1;
        final float u2 = 1;
        final float v2 = 0;
        final float fx2 = x + width;
        final float fy2 = y + height;

        final float color = tint.toFloatBits();

        vertices[idx++] = x;
        vertices[idx++] = y;
        vertices[idx++] = color;
        vertices[idx++] = u;
        vertices[idx++] = v;

        vertices[idx++] = x;
        vertices[idx++] = fy2;
        vertices[idx++] = color;
        vertices[idx++] = u;
        vertices[idx++] = v2;

        vertices[idx++] = fx2;
        vertices[idx++] = fy2;
        vertices[idx++] = color;
        vertices[idx++] = u2;
        vertices[idx++] = v2;

        vertices[idx++] = fx2;
        vertices[idx++] = y;
        vertices[idx++] = color;
        vertices[idx++] = u2;
        vertices[idx++] = v;
    }


    //    public void draw(Texture texture, float x, float y, float width, float height, Color tint) {
//        if (!drawing)
//            throw new IllegalStateException("you have to call SpriteBatch.begin() first");
//
//        if (texture != lastTexture) {
//            renderMesh();
//            lastTexture = texture;
//            invTexWidth = 1.0f / texture.getWidth();
//            invTexHeight = 1.0f / texture.getHeight();
//        }
//
//
//        float u = 0;
//        float v = 1;
//        float u2 = 1;
//        float v2 = 0;
//        final float fx2 = x + width;
//        final float fy2 = y + height;
//
//
//        final float color = tint.toFloatBits();
//
//        vertices[idx++] = x;
//        vertices[idx++] = y;
//        vertices[idx++] = color;
//        vertices[idx++] = u;
//        vertices[idx++] = v;
//
//        vertices[idx++] = x;
//        vertices[idx++] = fy2;
//        vertices[idx++] = color;
//        vertices[idx++] = u;
//        vertices[idx++] = v2;
//
//        vertices[idx++] = fx2;
//        vertices[idx++] = fy2;
//        vertices[idx++] = color;
//        vertices[idx++] = u2;
//        vertices[idx++] = v2;
//
//        vertices[idx++] = fx2;
//        vertices[idx++] = fy2;
//        vertices[idx++] = color;
//        vertices[idx++] = u2;
//        vertices[idx++] = v2;
//
//        vertices[idx++] = fx2;
//        vertices[idx++] = y;
//        vertices[idx++] = color;
//        vertices[idx++] = u2;
//        vertices[idx++] = v;
//
//        vertices[idx++] = x;
//        vertices[idx++] = y;
//        vertices[idx++] = color;
//        vertices[idx++] = u;
//        vertices[idx++] = v;
//
//        if (idx == vertices.length)
//            renderMesh();
//    }


    protected void renderMesh() {
        if (idx == 0)
            return;

        renderCalls++;

        lastTexture.bind();
        mesh.setVertices(vertices, 0, idx);

        if (Gdx.graphics.isGL20Available()) {
            mesh.render(shader, GL10.GL_TRIANGLES, 0, idx / 20 * 6);
        } else {
            mesh.render(GL10.GL_TRIANGLES, 0, idx / 20 * 6);
        }

        int spritesInBatch = idx / 20 / 6;
		if (spritesInBatch > maxSpritesInBatch) spritesInBatch = maxSpritesInBatch;
		idx = 0;
		currBufferIdx++;
		if(currBufferIdx == buffers.length) {
			currBufferIdx = 0;
		}
		mesh = buffers[currBufferIdx];
    }


    @Override
    public void setColor(Color tint) {
        GL.invalidateColor();
        super.setColor(tint);
    }

    @Override
    public void setColor(float r, float g, float b, float a) {
        GL.invalidateColor();
        super.setColor(r, g, b, a);
    }

    @Override
    public void setColor(float color) {
        GL.invalidateColor();
        super.setColor(color);
    }

    public BlendFunction getBlendFunction() {
        return blendFunction;
    }

    public void setBlendFunction(BlendFunction blendFunction) {
        this.blendFunction = blendFunction;
    }

    /**
     * Disposes all resources associated with this SpriteBatch
     */
    public void dispose() {
        mesh.dispose();
    }
}
